#!/usr/bin/env python3
# -*- coding:utf-8 -*-
u"""
所有flask示例，融合为一个页面

由与这只是一个简单的展示示例，所以尽量少用蓝图
但是在实际使用过程中，还是推荐尽量将不同的功能页面划分到不同的蓝图中
"""
import os
from flask import Flask
from flask import g
from flask import request
from flask import redirect
from flask import render_template
from flask import send_from_directory
from flask import url_for
from flask_bootstrap import Bootstrap
from flask_nav import Nav
from flask_nav.elements import Navbar, View
from flask_limiter import Limiter
from flask_limiter.util import get_remote_address
from flask_debugtoolbar import DebugToolbarExtension  # 一个非常好用的调试辅助模块
from flask_wtf import CSRFProtect

# 从其他脚本中导入蓝图模块
from src.api import api

# 导入设定好的wtforms
from src.form import AutocompleteForm

__author__ = "张一鸣"
__date__ = "2018.3.23"
__version__ = 0.1

__dir__ = os.path.dirname(os.path.abspath(__file__))
__download__ = os.path.join(__dir__, "files")


def create_app():
    app = Flask(__name__)
    app.debug = True   # 开启调试模式， 正式调试时，切记关闭
    nav = Nav()
    # 指定密钥
    app.config['SECRET_KEY'] = 'lcbb.swjtu.edu.cn'

    # 启用csrf加密保护措施
    csrf = CSRFProtect(app)
    csrf.init_app(app)

    # 开启调试模块
    DebugToolbarExtension(app)

    # 启用bootstrap
    Bootstrap(app)

    # 启用nav
    nav.init_app(app)

    # 注册蓝图
    app.register_blueprint(api, url_prefix="/api")
    return app, nav


app, nav = create_app()
limiter = Limiter(
    app,
    key_func=get_remote_address,
    default_limits=["200 per day", "50 per hour"]
)


@nav.navigation()
def mynavbar():
    return Navbar(
        'mysite',
        View('Home', 'index'),
        View("Autocomplete", "autocomplete")
    )


@app.before_request
def construct_links():
    u"""
    g是flask提供的一个环境，可以在其中储存部分数据
    则该flask app底下的任意脚本及html模板中的jinja语句可以通过g
    随时随地的访问该部分数据

    但是，前提就是需要往g中填充数据

    可以通过.号，像访问字典一样访问g中的数据

    比如：下方的例子中，以links为key值，向其中填充了一个字典
    """
    g.links = {
        "autocomplete": url_for("autocomplete"),
        "datatables": url_for("datatables"),
        "download": url_for("download"),
        "bootstrap": url_for("bootstrap")
    }


@app.route("/static_/<path:filename>")
def static_(filename):
    u'''
    新建一个通过本flask app提供静态文件的借口

    当同一台服务器上部署了不同风格的多个网页时（比如lcbb）
    通过自身的app提供静态文件最稳妥，最方便

    :param filename:文件名称加路径
                    绝对路径为/home/xxx/static/css/**.css，
                    此处filename为：css/**.css
    :return:返回整合文件
    '''
    # 设定静态文件夹的路径
    staticDirectory = os.path.join(__dir__, "static")
    return send_from_directory(directory=staticDirectory, filename=filename)


@app.route("/md/<path:filename>")
def markdown(filename):
    mdir = os.path.join(__dir__, "md/html")
    return send_from_directory(mdir, filename)


@app.route("/")
def index():
    u"""
    主页
    """
    return render_template("index.html")


@app.route("/autocomplete/", methods=["GET", "POST"])
def autocomplete():
    u"""
    展示自动补全的用法
    """
    autocomplete_form = AutocompleteForm()

    u"""
    通常通过request.method判断这个页面的访问方式，
    post通常是表明有个表单被提交了，而该页面上只有一个表达
    因此通过validator判断一下是否符合要求，不符合要求就可以做其他操作
    """
    if request.method == "POST":
        if autocomplete_form.validate():
            return "The message is: %s" % autocomplete_form.message.data
        else:
            return "Input error"
    return render_template("autocomplete/page.html", form=autocomplete_form, md=os.path.join(__dir__, "md/自动补全.md"))


@app.route("/datatables/")
def datatables():
    u"""
    展示datatables的用法
    """
    thead = [
        "chrom", "start", "end",
        "enhancerID", "tissue"
    ]
    return render_template("datatables/page.html", thead=thead)


@app.route("/_download/<path:filename>")
def download_file(filename):
    u"""
    提供下载的域名
    """
    file_dir = __download__
    return send_from_directory(file_dir, filename)


@app.route("/download/")
def download():
    u"""
    下载域名
    渲染下载页面
    """
    files = {}
    for f in os.listdir(__download__):
        files.update({f: os.path.getsize(os.path.join(__download__, f))})

    return render_template("download/page.html", files=files)


@app.route("/bootstrap/")
def bootstrap():
    return render_template("bootstrapTest/example.html")


def get_parameter(label, default=None):
    u"""
    request.args.get获取的字符串结果，可能环绕有各种空白字符等，需要记性strip
    """
    tem = request.args.get(label)

    if tem is None:
        return default
    return tem.strip()


@app.route("/limiter")
@app.route("/limiter/<int:freq>")
@limiter.limit("5 per day")
def limiterTest(freq=0):
    freq += 1
    return render_template("bootstrapTest/base.html", freq=freq)


if __name__ == '__main__':
    app.run(host="127.0.0.1", port=5000, debug=True, )
